/**
 * 获取access_token
 *      是什么？微信调用接口全局唯一凭据
 *      特点：唯一的，有效期为2小时，有权限每天2000次
 *
 * 请求地址：（get请求）
 *  https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
 *
 * 设计思路
 *  1.首次本地没有，发送请求获取access_token，保存下来（本地文件）
 *  2.第二次或以后：先去本地读取文件，判读是否过期（过期：重新获取，并保存；没过期：直接使用）
 *
 *  request-promise-native，返回值是一个promise对象
 *
 */
const rpn = require('request-promise-native');
const {writeFile, readFile} = require('fs');
const {appID, appsecret} = require('../config/index');
const {access_token_api} = require('../config/api');

// 请求access_token
const getAccessToken = () => {
    const url = `${access_token_api}&appid=${appID}&secret=${appsecret}`;
    // 发送请求
    return new Promise((resolve, reject) => {
        rpn({
            method: 'GET',
            url,
            json: true
        })
            .then(res => {
                console.log(res);
                /**
                 {
                     access_token: 'xxxxxxx',
                     expires_in: 7200
                 }
                 */
                // 设置access_token的过期时间
                res.expires_in = Date.now() + (res.expires_in - 300) * 1000;

                resolve(res);

            })
            .catch(err => {
                console.log(err);
                reject('getAccessToken出错：' + err);
            });
    });
};

// 保存access_token
const saveAccessToken = (data) => {
    return new Promise((resolve, reject) => {
        writeFile('./accessToken.txt', JSON.stringify(data), err => {
            if (!err) {
                console.log("文件保存成功...");
                resolve();
            } else {
                reject('saveAccessToken出错：' + err);
            }
        });
    });
}

// 读取access_token
const readAccessToken = () => {
    return new Promise((resolve, reject) => {
        readFile('./accessToken.txt', (err, data) => {
            if (!err) {
                console.log("文件读取成功...");
                resolve(JSON.parse(data));
            } else {
                reject('readAccessToken出错：' + err);
            }
        });
    });
}

// 判断access_token是否有效
const isValidAccessToken = (data) => {
    if (!data && !data.access_token && !data.expires_in) {
        return false;
    }
    if (data.expires_in < Date.now()) {
        return false;
    }
    return true;
}

module.exports = {
    // 获取有效的access_token
    fetchAccessToken() {
        if (this.access_token && this.expires_in && isValidAccessToken(this)) {
            return Promise.resolve({
                access_token: this.access_token,
                expires_in: this.expires_in
            });
        }
        return readAccessToken()
            .then(async res => {
                if (isValidAccessToken(res)) {
                    return Promise.resolve(res);
                } else {
                    const res = await getAccessToken();
                    await saveAccessToken(res);
                    return Promise.resolve(res);
                }
            })
            .catch(async err => {
                const res = await getAccessToken();
                await saveAccessToken(res);
                return Promise.resolve(res);
            })
            .then(res => {
                this.access_token = res.access_token;
                this.expires_in = res.expires_in;
                return Promise.resolve(res);
            })
    }
}